﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using CheckersBoardEngine;

namespace EngineAdmin
{
    /// <summary>
    /// Checkers Board Engine Manager
    /// </summary>
    public class CBEngineManager
    {
        /// <summary>
        /// The list of installed CB Engines
        /// </summary>
        private List<CBEngineFacade> _installedEngines = null;

        /// <summary>
        /// Constructor
        /// </summary>
        public CBEngineManager()
        {
            _installedEngines = new List<CBEngineFacade>();
        }

        #region Public Interface

        /// <summary>
        /// Output error
        /// </summary>
        public string ErrorMessage
        { get; set; }

        /// <summary>
        /// Installs the new CB Engine
        /// </summary>
        public CBEngineFacade InstallEngine(string enginePath)
        {
            if (File.Exists(enginePath) == false)
            {
                return null;
            }

            CBEngineFacade cbEngine = new CBEngineFacade(enginePath);
            _installedEngines.Add(cbEngine);
            return cbEngine;
        }

        
        /// <summary>
        /// Removes the installed engine
        /// </summary>
        public void RemoveEngine(CBEngineFacade cbEngine)
        {
            if (_installedEngines.Contains(cbEngine))
            {
                if (cbEngine.IsLoaded)
                {
                    cbEngine.UnloadEngine();
                }

                _installedEngines.Remove(cbEngine);
            }
        }

        /// <summary>
        /// Loads the engine
        /// </summary>
        public bool LoadEngine(CBEngineFacade cbEngine)
        {
            if (cbEngine.LoadEngine() == false)
            {
                ErrorMessage = cbEngine.ErrorMessage;
                return false;
            }

            return true;
        }

        /// <summary>
        /// Removes the engine resources from the memory
        /// </summary>
        public void UnloadEngine(CBEngineFacade cbEngine)
        {
            try
            {
                cbEngine.UnloadEngine();
            }
            catch
            {
            }
        }

        /// <summary>
        /// Termination method - frees all CB engines
        /// </summary>
        public void TerminateEngines()
        {
            foreach (var engine in _installedEngines)
            {
                if (engine.IsLoaded)
                {
                    engine.UnloadEngine();
                }
            }
        }

        /// <summary>
        /// Returns the list of installed engines
        /// </summary>
        public List<CBEngineFacade> GetListOfInstalledEngines()
        {
            List<CBEngineFacade> installedEngines = new List<CBEngineFacade>();
            installedEngines.AddRange(_installedEngines);
            return installedEngines;
        }

        /// <summary>
        /// Returns the list of loaded engines
        /// </summary>
        /// <returns></returns>
        public List<CBEngineFacade> GetListOfLoadedEngines()
        {
            List<CBEngineFacade> loadedEngines = new List<CBEngineFacade>();

            foreach (var engine in _installedEngines)
            {
                if (engine.IsLoaded)
                    loadedEngines.Add(engine);
            }

            return loadedEngines;
        }

        /// <summary>
        /// Get the list of installed but not yet loaded engines
        /// </summary>
        public List<CBEngineFacade> GetListOfUnloadedEngines()
        {
            List<CBEngineFacade> loadedEngines = new List<CBEngineFacade>();

            foreach (var engine in _installedEngines)
            {
                if (! engine.IsLoaded)
                    loadedEngines.Add(engine);
            }

            return loadedEngines;
        }

        /// <summary>
        /// Returns configuration for save to the global config cache
        /// </summary>
        public List<CBEngineSettings> GetConfigForSave()
        {
            List<CBEngineSettings> lstConfigs = new List<CBEngineSettings>();

            foreach (var engine in _installedEngines)
            {
                lstConfigs.Add(engine.GetSettingsForSave());
            }

            return lstConfigs;
        }

        /// <summary>
        /// Restores the state of CB Manager Engines from the configuration
        /// </summary>
        public void RestoreFromConfig(List<CBEngineSettings> lstConfigs)
        {
            foreach (var config in lstConfigs)
            {
                var engine = InstallEngine(config.EnginePath);
                if (config.IsLoaded)
                    LoadEngine(engine);                                 
            }
        }

        #endregion

        /// <summary>
        /// Singleton instance
        /// </summary>
        private static CBEngineManager _instance = null;

        /// <summary>
        /// Factory Method
        /// </summary>
        public static CBEngineManager Instance()
        {
            if (_instance == null)
                _instance = new CBEngineManager();
            return _instance;
        }
    }
}